package com.example.wenhua.service.impl;

import com.example.wenhua.entity.Sc;
import com.example.wenhua.mapper.ScMapper;
import com.example.wenhua.mapper.StudentMapper;
import com.example.wenhua.mapper.CourseMapper;
import com.example.wenhua.service.ScService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * 选课业务逻辑实现类
 */
@Service
public class ScServiceImpl implements ScService {
    
    @Autowired
    private ScMapper scMapper;
    
    @Autowired
    private StudentMapper studentMapper;
    
    @Autowired
    private CourseMapper courseMapper;
    
    @Override
    public List<Map<String, Object>> getAllScRecords() {
        return scMapper.findAll();
    }
    
    @Override
    public List<Map<String, Object>> getScRecordsWithFilter(String sno, String cno, String gradeStatus) {
        return scMapper.findWithFilter(sno, cno, gradeStatus);
    }
    
    @Override
    public List<Sc> getScRecordsBySno(String sno) {
        return scMapper.findBySno(sno);
    }
    
    @Override
    public List<Sc> getScRecordsByCno(String cno) {
        return scMapper.findByCno(cno);
    }
    
    @Override
    @Transactional
    public boolean selectCourse(String sno, String cno) {
        // 检查学生是否存在
        if (studentMapper.findBySno(sno) == null) {
            throw new RuntimeException("学生不存在：" + sno);
        }
        
        // 检查课程是否存在
        if (courseMapper.findByCno(cno) == null) {
            throw new RuntimeException("课程不存在：" + cno);
        }
        
        // 检查是否已选课
        if (scMapper.findBySnoAndCno(sno, cno) != null) {
            throw new RuntimeException("学生已选择该课程");
        }
        
        Sc sc = new Sc(sno, cno, null);
        return scMapper.insert(sc) > 0;
    }
    
    @Override
    @Transactional
    public boolean dropCourse(String sno, String cno) {
        // 检查选课记录是否存在
        if (scMapper.findBySnoAndCno(sno, cno) == null) {
            throw new RuntimeException("选课记录不存在");
        }
        
        return scMapper.delete(sno, cno) > 0;
    }
    
    @Override
    @Transactional
    public boolean updateGrade(String sno, String cno, BigDecimal grade) {
        // 检查选课记录是否存在
        if (scMapper.findBySnoAndCno(sno, cno) == null) {
            throw new RuntimeException("选课记录不存在");
        }
        
        // 检查成绩范围
        if (grade != null && (grade.compareTo(BigDecimal.ZERO) < 0 || grade.compareTo(new BigDecimal("100")) > 0)) {
            throw new RuntimeException("成绩必须在0-100之间");
        }
        
        return scMapper.updateGrade(sno, cno, grade) > 0;
    }
    
    @Override
    public List<Map<String, Object>> getStudentGradesBySno(String sno) {
        return scMapper.getStudentGradesBySno(sno);
    }
    
    @Override
    public List<Map<String, Object>> getFailStudentsByCno(String cno) {
        return scMapper.getFailStudentsByCno(cno);
    }
    
    @Override
    public List<Map<String, Object>> getFailStatsByDept() {
        List<Map<String, Object>> stats = scMapper.getFailStatsByDept();
        
        // 计算不及格比例
        for (Map<String, Object> stat : stats) {
            Integer failCount = (Integer) stat.get("failCount");
            Integer totalCount = (Integer) stat.get("totalCount");
            if (totalCount > 0) {
                double failRate = (double) failCount / totalCount * 100;
                stat.put("failRate", Math.round(failRate * 100.0) / 100.0); // 保留两位小数
            } else {
                stat.put("failRate", 0.0);
            }
        }
        
        return stats;
    }
    
    @Override
    public List<Map<String, Object>> getGradeRangeStatsByDept() {
        List<Map<String, Object>> stats = scMapper.getGradeRangeStatsByDept();
        
        // 计算各分数段比例
        for (Map<String, Object> stat : stats) {
            Long range0_59 = (Long) stat.get("range0_59");
            Long range60_69 = (Long) stat.get("range60_69");
            Long range70_79 = (Long) stat.get("range70_79");
            Long range80_89 = (Long) stat.get("range80_89");
            Long range90_100 = (Long) stat.get("range90_100");
            
            long total = range0_59 + range60_69 + range70_79 + range80_89 + range90_100;
            
            if (total > 0) {
                stat.put("rate0_59", Math.round((double) range0_59 / total * 10000.0) / 100.0);
                stat.put("rate60_69", Math.round((double) range60_69 / total * 10000.0) / 100.0);
                stat.put("rate70_79", Math.round((double) range70_79 / total * 10000.0) / 100.0);
                stat.put("rate80_89", Math.round((double) range80_89 / total * 10000.0) / 100.0);
                stat.put("rate90_100", Math.round((double) range90_100 / total * 10000.0) / 100.0);
            }
            
            stat.put("totalCount", total);
        }
        
        return stats;
    }
    
    @Override
    public boolean isStudentEnrolled(String sno, String cno) {
        return scMapper.findBySnoAndCno(sno, cno) != null;
    }
}